#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

/*定义不定参宏函数*/
#define Log(format,...) printf("[%s:%d]" format"\n",__FILE__,__LINE__,##__VA_ARGS__)

/*定义不定参函数*/
void myprint(const char* format,...)
{
    va_list ap;
    va_start(ap,format);
    char buffer[32]={0};
    bzero(buffer,sizeof(buffer));
    vsnprintf(buffer,sizeof(buffer)-1,format,ap);
    va_end(ap);
    printf("%s",buffer);
}

/*使用va_arg宏*/
int mysum(int count,...)
{
    va_list ap;
    va_start(ap,count);
    int sum=0;
    for(int i=0;i<count;i++)
    {
        sum+=va_arg(ap,int);
    }
    va_end(ap);
    return sum;
}

void my_print(const char* format,...)
{
    char* str=NULL;
    va_list ap;
    va_start(ap,format);
    if(vasprintf(&str,format,ap)<0)
    {
        //执行失败
        fprintf(stderr,"vasprintf failed\n");
        va_end(ap);
        return;
    }
    va_end(ap);
    printf("%s",str);
    free(str);//很关键，需要手动释放vasprintf函数内部开辟的空间
}

/*模拟实现*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define BUFFER_SIZE 1024
void my_printf(const char* format,...)
{
    char buffer[BUFFER_SIZE];//存储最终结果的缓冲区
    bzero(buffer,sizeof(buffer));
    char* res=buffer;//指向buffer的指针
    const char* fptr=format;//format解析指针

    va_list ap;//ap指针
    va_start(ap,format);//初始化ap指针，使其指向可变参数列表第一个参数

    //开始循环遍历format格式化字符串
    while(*fptr!='\0')
    {
        if(*fptr!='%')
        {
            //当当前字符不为%时，直接将字符赋值进缓冲区中
            *res++=*fptr++;
            continue;
        }
        
        //走到这里匹配到了%格式
        fptr++;//移动fptr指针跳过%
        char ch=0;
        int i=0;
        char* s=NULL;
        unsigned int u=0;
        double f=0.0;
        //根据%后面具体格式判断解析
        switch(*fptr)
        {
            case 'c':
                ch=va_arg(ap,int);
                *res++=ch;
                break;
            case 'd': 
                i=va_arg(ap,int);
                res+=sprintf(res,"%d",i);
                break;
            case 's': 
                s=va_arg(ap,char*);
                while(*s) *res++=*s++;
                break;
            case 'u': 
                u=va_arg(ap,unsigned int);
                res+=sprintf(res,"%u",u);
                break;
            case 'f': 
                f=va_arg(ap,double);
                res+=sprintf(res,"%f",f);
                break;
            default: 
                *res++='%';
                *res++=*fptr;
                break;
        }
        fptr++;
    }

    *res='\0';
    int len=res-buffer;
    write(1,buffer,len);
    va_end(ap);//将ap指针置空
}

int main()
{
    // Log("hello world");
    // Log("%s","世界你好");
    //myprint("%s\n","hello world");
    //printf("sum=%d\n",mysum(3,1,2,3));
    //my_print("%s\n","hello world");
    my_printf("Hello %s! The number is %d and the character is %c.\n", "World", 42, 'A');
    my_printf("Unsigned integer: %u, Floating point: %f\n", 12345, 3.14159);
    return 0;
}